package com.iplay.service.query.and;

import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.iplay.listener.SpringContextHolder;
import com.iplay.service.query.Query;
import com.iplay.service.query.QueryBuilder;
import com.iplay.service.query.QueryCondition;
import com.iplay.service.query.QueryCondition.Operator;
import com.iplay.service.query.QueryConditionBuilder;

@Service
public class AndQueryBuilder<T> implements QueryBuilder<T> {

	private static final Logger LOGGER = LoggerFactory.getLogger(AndQueryBuilder.class);

	@Override
	public Query create(T t) {
		List<QueryCondition> queryConditions = new LinkedList<>();
		Field[] fields = t.getClass().getDeclaredFields();
		for (Field f : fields) {
			QueryCondition queryCondition = null;
			try {
				f.setAccessible(true);
				Object value = f.get(t);
				if(value == null)
					continue;
				if (f.isAnnotationPresent(com.iplay.service.query.annotation.QueryCondition.class)) {
					com.iplay.service.query.annotation.QueryCondition queryConditionAnnotation = f
							.getAnnotation(com.iplay.service.query.annotation.QueryCondition.class);
					if (queryConditionAnnotation.ignore())
						continue;
					if (queryConditionAnnotation.builder() != QueryConditionBuilder.class) {
						queryCondition = SpringContextHolder.getBean(queryConditionAnnotation.builder()).create(value);
					} else {
						queryCondition = new QueryCondition(emptyOrDefault(queryConditionAnnotation.value(), f.getName()),
								queryConditionAnnotation.operator(), value);
					}
				} else {
					queryCondition = new QueryCondition(f.getName(), Operator.EQ, value);
				}
				queryConditions.add(queryCondition);
			} catch (IllegalAccessException | IllegalArgumentException e) {
				LOGGER.error(e.getMessage(), e);
			}
		}
		return new AndQuery(queryConditions);
	}

	private <C> C emptyOrDefault(C t, C defaultValue) {
		if (t == null||(t.getClass()==String.class&&String.class.cast(t).equals("")))
			return defaultValue;
		return t;
	}
}
